package com.zb.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;

import com.zb.util.annotation.AnnotationUtils;
import com.zb.util.annotation.Ignore;

/**
 * 反射帮助类
 * 
 * @author 谢龙飞
 * 
 */
public final class ReflectUtils {

	/**
	 * 通过对象、属性名称和类得到Get方法名称
	 * 
	 * @param obj
	 *            对象
	 * @param fieldName
	 *            属性名称
	 * @param cls
	 *            类
	 * @return
	 */
	public static final Object invokeObjectReadMethodByFieldNameAndClass(
			Object obj, String fieldName, Class<?> cls) {

		PropertyDescriptor descriptor;
		try {
			descriptor = new PropertyDescriptor(fieldName, cls);
			// 得到get方法
			Method method = descriptor.getReadMethod();
			if (method == null) {
				return null;
			}
			// 调用
			return method.invoke(obj);
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | IntrospectionException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 向属性中写入值（调用set方法）
	 * 
	 * @param obj
	 * @param cls
	 * @return
	 */
	public static final boolean invokeObjectWriteMethodByFieldNameAndClass(
			Object obj, Field field, Class<?> cls, Object fieldObj) {

		PropertyDescriptor descriptor;
		try {
			descriptor = new PropertyDescriptor(field.getName(), cls);
			// 得到set方法
			Method method = descriptor.getWriteMethod();
			fieldObj += "";
			// 得到属性类型
			Class<?> typeName = field.getType();

			// 判断类型并调用set方法
			if (typeName.equals(Integer.class)) {
				Integer fieldValue = (Integer) fieldObj;
				method.invoke(obj, fieldValue);
			} else if (typeName.equals(Double.class)) {
				Double fieldValue = (Double) fieldObj;
				method.invoke(obj, fieldValue);
			} else if (typeName.equals(String.class)) {
				String fieldValue = (String) fieldObj;
				method.invoke(obj, fieldValue);
			} else if (typeName.equals(Short.class)) {
				Short fieldValue = (Short) fieldObj;
				method.invoke(obj, fieldValue);
			} else if (typeName.equals(Float.class)) {
				Float fieldValue = (Float) fieldObj;
				method.invoke(obj, fieldValue);
			}
			return true;
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | IntrospectionException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 设置属性值
	 * 
	 * @param field
	 *            属性对象
	 * @param obj
	 *            设置对象
	 * @param rs
	 *            数据resultset
	 * @param cls
	 *            类
	 */
	public static final void setFieldsValue(Field field, ResultSet rs,
			Object obj, Class<?> cls) {

		try {
			Object fieldObj = rs.getObject(field.getName());
			if (fieldObj != null) {
				PropertyDescriptor descriptor = new PropertyDescriptor(
						field.getName(), cls);
				// 得到set方法
				Method method = descriptor.getWriteMethod();
				Class<?> fieldType = field.getType();
				if (fieldType.equals(Integer.class)) {
					Integer fieldValue = (Integer) fieldObj;
					method.invoke(obj, fieldValue);
				} else if (fieldType.equals(Double.class)) {
					Double fieldValue = (Double) fieldObj;
					method.invoke(obj, fieldValue);
				} else if (fieldType.equals(String.class)) {
					String fieldValue = (String) fieldObj;
					method.invoke(obj, fieldValue);
				} else if (fieldType.equals(Short.class)) {
					Short fieldValue = (Short) fieldObj;
					method.invoke(obj, fieldValue);
				} else if (fieldType.equals(Float.class)) {
					Float fieldValue = (Float) fieldObj;
					method.invoke(obj, fieldValue);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置查询的列
	 * 
	 * @param fields
	 * @param tableName
	 */
	public static String setQueryColumn(Field[] fields, String tableName) {

		StringBuffer sqlBuffer = new StringBuffer();

		// 设置查询的列（所有）
		for (Field field : fields) {

			boolean modifier = ((field.getModifiers() & Modifier.STATIC) != 0 || (field
					.getModifiers() & Modifier.FINAL) != 0);

			if (!modifier) {
				//是否为忽略映射属性
				if(!AnnotationUtils.ignore(field)){
					sqlBuffer.append('`');
					sqlBuffer.append(field.getName());
					sqlBuffer.append('`');
					sqlBuffer.append(",");
				}
			}
		}
		// 删除最后一个逗号
		sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
		return sqlBuffer.toString();
	}

	/**
	 * 通过修饰符判断属性是否可用
	 * 
	 * @param field
	 * @return
	 */
	public static boolean judgeModifiersAvailable(Field field) {

		return ((field.getModifiers() & Modifier.STATIC) != 0
				|| (field.getModifiers() & Modifier.FINAL) != 0
				|| (field.getModifiers() & Modifier.VOLATILE) != 0 || (field
						.getModifiers() & Modifier.TRANSIENT) != 0);

	}

	//********************20160406 perlin add start****************************//
	public static Object setQueryColumnWithIgnore(Field[] fields,
			String tableName) {
		StringBuffer sqlBuffer = new StringBuffer();

		// 设置查询的列（所有）
		for (Field field : fields) {

			boolean modifier = ((field.getModifiers() & Modifier.STATIC) != 0 || (field
					.getModifiers() & Modifier.FINAL) != 0);

			if (!modifier) {
				Ignore ignore = field.getAnnotation(Ignore.class);
				//没有ignore注释 ，或者有ignore注释但是属性为otherTable的列  返回
				if(ignore==null||(ignore!=null&&ignore.isOtherTable())){
					sqlBuffer.append('`');
					sqlBuffer.append(field.getName());
					sqlBuffer.append('`');
					sqlBuffer.append(",");
				}

			}
		}
		// 删除最后一个逗号
		sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
		return sqlBuffer.toString();
	}
	//********************20160406 perlin add end****************************//

}
